package me.flyray.bsin.server.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.profitsharing.notify.ProfitSharingNotifyV3Result;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.domain.entity.Transaction;
import me.flyray.bsin.domain.entity.PayChannelConfig;
import me.flyray.bsin.domain.enums.TransactionStatus;
import me.flyray.bsin.dubbo.invoke.BsinServiceInvoke;
import me.flyray.bsin.facade.service.ProfitSharingJournalService;
import me.flyray.bsin.infrastructure.biz.paychannel.PayChannelConfigBiz;
import me.flyray.bsin.infrastructure.mapper.TransactionMapper;
import me.flyray.bsin.payment.channel.wxpay.WxServiceUtil;
import org.apache.shenyu.client.apidocs.annotations.ApiDoc;
import org.apache.shenyu.client.apidocs.annotations.ApiModule;
import org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 分账回调处理控制器
 * 专门处理各种支付渠道分账回调的控制器，目前主要实现了微信支付的分账回调处理
 * 支持 V2 和 V3 接口，完全兼容服务商、普通商户、特约商户等不同模式
 * 
 * 参考：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
 */
@RestController
@RequestMapping("/profitSharingCallback")
@ShenyuSpringMvcClient("/profitSharingCallback/**")
@ApiModule(value = "profitSharingCallback")
@Slf4j
public class ProfitSharingCallbackController {

    @Autowired
    private PayChannelConfigBiz payChannelConfigBiz;
    
    @Autowired
    private TransactionMapper transactionMapper;
    
    @Autowired
    private ProfitSharingJournalService profitSharingJournalService;
    
    @Autowired
    private BsinServiceInvoke bsinServiceInvoke;

    /**
     * 微信分账回调处理（完全兼容 v2 和 v3，支持服务商、普通商户、特约商户）
     *
     * 支持的回调类型：
     * 1. 普通商户分账回调（v2/v3）
     * 2. 服务商子商户分账回调（v2/v3）
     * 3. 特约商户分账回调（v2/v3）
     *
     * 处理流程：
     * 1. 根据 outOrderNo 查询分账订单信息
     * 2. 获取支付渠道配置
     * 3. 解析回调数据（自动识别 v2/v3）
     * 4. 验证签名和更新分账状态
     * 5. 更新分账流水状态
     * 6. 调用业务模块处理分账结果
     *
     * @param body 回调数据
     * @param outOrderNo 分账单号
     * @param headers 回调头信息
     * @return 处理结果
     * @throws Exception 处理异常
     */
    @PostMapping("/wxpay/{outOrderNo}")
    @ApiDoc(desc = "wxpay")
    public Object wxpay(
            @RequestBody(required = false) String body,
            @PathVariable("outOrderNo") String outOrderNo,
            @RequestHeader Map<String, String> headers)
            throws Exception {
        
        try {
            log.info("微信分账回调开始处理，分账单号: {}", outOrderNo);
            log.info("回调数据body: {}", body);
            log.info("回调头headers: {}", headers);

            // 1. 根据 outOrderNo 查询分账订单信息
            Transaction transaction = transactionMapper.selectOne(
                new LambdaQueryWrapper<Transaction>().eq(Transaction::getOutOrderNo, outOrderNo));

            if (transaction == null) {
                log.error("未找到对应的分账订单，分账单号: {}", outOrderNo);
                return WxPayNotifyResponse.fail("分账订单不存在");
            }

            log.info("查询到分账订单: {}", transaction);

            // 2. 根据订单信息查询支付渠道配置
            String payChannelConfigNo = transaction.getPayChannelConfigNo();
            if (payChannelConfigNo == null || payChannelConfigNo.isEmpty()) {
                log.error("分账订单未关联支付渠道配置，分账单号: {}", outOrderNo);
                return WxPayNotifyResponse.fail("支付渠道配置不存在");
            }

            log.info("支付渠道配置编号: {}", payChannelConfigNo);

            // 3. 获取微信支付服务（支持 v2 和 v3）
            WxServiceUtil wxServiceUtil = payChannelConfigBiz.getWxServiceWrapper(payChannelConfigNo);
            WxPayService wxPayService = wxServiceUtil.getWxPayService();

            // 获取支付渠道配置信息
            PayChannelConfig payChannelConfig = payChannelConfigBiz.getPayChannelConfig(payChannelConfigNo);
            if (payChannelConfig == null) {
                log.error("未找到支付渠道配置，payChannelConfigNo: {}", payChannelConfigNo);
                return WxPayNotifyResponse.fail("支付渠道配置不存在");
            }

            Map<String, Object> requestMap = new HashMap<>();

            // 4. 智能解析微信分账回调数据（根据配置自动识别版本和商户模式）
            if ("V3".equals(wxServiceUtil.getApiVersion())) {
                log.info("微信分账V3回调");
                
                // 构建签名头
                SignatureHeader header = SignatureHeader.builder()
                        .timeStamp(headers.get("wechatpay-timestamp"))
                        .nonce(headers.get("wechatpay-nonce"))
                        .signature(headers.get("wechatpay-signature"))
                        .serial(headers.get("wechatpay-serial"))
                        .build();
                
                try {
                    // 尝试通过ProfitSharingService解析分账回调
                    ProfitSharingService profitSharingService = wxPayService.getProfitSharingService();
                    ProfitSharingNotifyV3Result result = profitSharingService.parseProfitSharingNotifyResult(body, header);
                    log.info("微信分账回调解析成功：{}", result.toString());
                    
                    // 由于WxJava库版本差异，这里使用JSON解析的方式获取关键信息
                    // 这样可以避免类型兼容性问题
                    JSONObject jsonBody = JSONObject.parseObject(body);
                    if (jsonBody != null) {
                        requestMap.put("resultCode", jsonBody.getString("state"));
                        requestMap.put("orderNo", jsonBody.getString("out_order_no"));
                        requestMap.put("transactionId", jsonBody.getString("transaction_id"));
                        requestMap.put("stateDesc", jsonBody.getString("state_desc"));
                        
                        // 验证必要字段
                        if (jsonBody.getString("state") == null) {
                            log.error("微信分账V3回调解析失败，state为空");
                            return WxPayNotifyResponse.fail("分账回调解析失败");
                        }
                    }
                    
                } catch (Exception e) {
                    log.warn("通过ProfitSharingService解析失败，尝试直接JSON解析：{}", e.getMessage());
                    
                    // 降级处理：直接解析JSON
                    try {
                        JSONObject jsonBody = JSONObject.parseObject(body);
                        if (jsonBody != null) {
                            requestMap.put("resultCode", jsonBody.getString("state"));
                            requestMap.put("orderNo", jsonBody.getString("out_order_no"));
                            requestMap.put("transactionId", jsonBody.getString("transaction_id"));
                            requestMap.put("stateDesc", jsonBody.getString("state_desc"));
                            
                            // 验证必要字段
                            if (jsonBody.getString("state") == null) {
                                log.error("微信分账V3回调JSON解析失败，state为空");
                                return WxPayNotifyResponse.fail("分账回调解析失败");
                            }
                        } else {
                            log.error("微信分账V3回调JSON解析失败，body为空");
                            return WxPayNotifyResponse.fail("分账回调解析失败");
                        }
                    } catch (Exception jsonEx) {
                        log.error("微信分账V3回调JSON解析完全失败", jsonEx);
                        return WxPayNotifyResponse.fail("分账回调解析失败");
                    }
                }
                
            } else {
                log.info("微信分账V2回调");
                // V2分账回调处理（如果有的话）
                // 注意：微信支付V2接口可能不支持分账回调，这里预留处理逻辑
                log.warn("微信支付V2接口可能不支持分账回调，建议升级到V3接口");
                return WxPayNotifyResponse.fail("V2接口不支持分账回调");
            }

            // 添加商户模式信息
            requestMap.put("merchantPayMode", payChannelConfig.getMerchantPayMode());
            requestMap.put("payWay", payChannelConfig.getPayWay());
            requestMap.put("bizRoleAppId", payChannelConfig.getBizRoleAppId());
            requestMap.put("bizRoleTypeNo", payChannelConfig.getBizRoleTypeNo());

            // 5. 处理分账回调结果
            boolean success = processProfitSharingResult(requestMap, transaction);
            if (!success) {
                log.error("处理分账回调结果失败，分账单号: {}", outOrderNo);
                return WxPayNotifyResponse.fail("分账回调处理失败");
            }

            // 6. 异步调用（泛化调用解耦）分账完成方法统一处理
            bsinServiceInvoke.genericInvoke("ProfitSharingService", "completeProfitSharing", "dev", requestMap);

            log.info("微信分账回调处理完成，分账单号: {}", outOrderNo);
            return WxPayNotifyResponse.success("success");

        } catch (Exception e) {
            log.error("微信分账回调处理失败，分账单号: {}, 错误信息: {}", outOrderNo, e.getMessage(), e);
            return WxPayNotifyResponse.fail("分账回调处理失败");
        }
    }

    /**
     * 处理分账回调结果
     */
    private boolean processProfitSharingResult(Map<String, Object> requestMap, Transaction transaction) {
        try {
            String resultCode = (String) requestMap.get("resultCode");
            String outOrderNo = (String) requestMap.get("orderNo");
            String transactionId = (String) requestMap.get("transactionId");
            String stateDesc = (String) requestMap.get("stateDesc");

            log.info("处理分账回调结果，分账单号：{}，微信订单号：{}，状态：{}，描述：{}", 
                    outOrderNo, transactionId, resultCode, stateDesc);

            // 根据分账状态处理
            if ("SUCCESS".equals(resultCode)) {
                return handleProfitSharingSuccess(outOrderNo, transactionId, transaction);
            } else if ("FAILED".equals(resultCode)) {
                return handleProfitSharingFailure(outOrderNo, transactionId, stateDesc, transaction);
            } else {
                log.warn("未知的分账状态：{}", resultCode);
                return false;
            }

        } catch (Exception e) {
            log.error("处理分账回调结果失败", e);
            return false;
        }
    }

    /**
     * 处理分账成功
     */
    @Transactional(rollbackFor = Exception.class)
    private boolean handleProfitSharingSuccess(String outOrderNo, String transactionId, Transaction transaction) {
        try {
            log.info("分账成功，分账单号：{}，微信订单号：{}", outOrderNo, transactionId);

            // 1. 更新交易分账状态
            transaction.setProfitSharingStatus(true);
            transaction.setTransactionStatus(TransactionStatus.SUCCESS.getCode());
            transactionMapper.updateById(transaction);

            // 2. 更新分账流水状态
            updateProfitSharingJournalStatus(outOrderNo, "SUCCESS");

            // 3. 记录分账成功日志
            recordProfitSharingSuccess(outOrderNo, transactionId);

            return true;

        } catch (Exception e) {
            log.error("处理分账成功失败", e);
            return false;
        }
    }

    /**
     * 处理分账失败
     */
    @Transactional(rollbackFor = Exception.class)
    private boolean handleProfitSharingFailure(String outOrderNo, String transactionId, String errorMsg, Transaction transaction) {
        try {
            log.warn("分账失败，分账单号：{}，微信订单号：{}，失败原因：{}", outOrderNo, transactionId, errorMsg);

            // 1. 更新交易分账状态
            transaction.setProfitSharingStatus(false);
            transaction.setTransactionStatus(TransactionStatus.FAIL.getCode());
            transactionMapper.updateById(transaction);

            // 2. 更新分账流水状态
            updateProfitSharingJournalStatus(outOrderNo, "FAILED");

            // 3. 记录分账失败日志
            recordProfitSharingFailure(outOrderNo, transactionId, errorMsg);

            return true;

        } catch (Exception e) {
            log.error("处理分账失败失败", e);
            return false;
        }
    }

    /**
     * 更新分账流水状态
     */
    private void updateProfitSharingJournalStatus(String outOrderNo, String status) {
        try {
            Map<String, Object> updateMap = new HashMap<>();
            updateMap.put("outOrderNo", outOrderNo);
            updateMap.put("status", status);
            
            // TODO: 调用分账流水服务更新状态
            // profitSharingJournalService.updateStatus(updateMap);
            log.info("分账流水状态更新成功，分账单号：{}，状态：{}", outOrderNo, status);
            
        } catch (Exception e) {
            log.error("更新分账流水状态失败，分账单号：{}", outOrderNo, e);
        }
    }

    /**
     * 记录分账成功日志
     */
    private void recordProfitSharingSuccess(String outOrderNo, String transactionId) {
        try {
            log.info("分账成功记录，分账单号：{}，微信订单号：{}", outOrderNo, transactionId);
            
            // TODO: 可以在这里添加分账成功后的业务逻辑
            // 比如：发送通知、更新统计、触发后续流程等
            
        } catch (Exception e) {
            log.error("记录分账成功日志失败，分账单号：{}", outOrderNo, e);
        }
    }

    /**
     * 记录分账失败日志
     */
    private void recordProfitSharingFailure(String outOrderNo, String transactionId, String errorMsg) {
        try {
            log.warn("分账失败记录，分账单号：{}，微信订单号：{}，错误信息：{}", outOrderNo, transactionId, errorMsg);
            
            // TODO: 可以在这里添加分账失败后的业务逻辑
            // 比如：发送告警、重试机制、人工处理等
            
        } catch (Exception e) {
            log.error("记录分账失败日志失败，分账单号：{}", outOrderNo, e);
        }
    }

    /**
     * 支付宝分账回调接口（预留）
     */
    @PostMapping("/alipay/{outOrderNo}")
    @ApiDoc(desc = "alipay")
    public Object alipay(
            @RequestBody(required = false) String body, 
            @PathVariable("outOrderNo") String outOrderNo) throws Exception {
        // TODO: 实现支付宝分账回调处理
        log.info("支付宝分账回调，分账单号: {}", outOrderNo);
        return "success";
    }

    /**
     * 银联分账回调接口（预留）
     */
    @PostMapping("/unionpay/{outOrderNo}")
    @ApiDoc(desc = "unionpay")
    public Object unionpay(
            @RequestBody(required = false) String body, 
            @PathVariable("outOrderNo") String outOrderNo) throws Exception {
        // TODO: 实现银联分账回调处理
        log.info("银联分账回调，分账单号: {}", outOrderNo);
        return "success";
    }
} 